package fgame.controller
{
	import fgame.GameState;
	import fgame.action.MoveAct;
	import fgame.controller.state.AttackState;
	import fgame.controller.state.ControllState;
	import fgame.controller.state.JumpState;
	import fgame.controller.state.MapClickState;
	import fgame.controller.state.MoveState;
	import fgame.controller.state.State;
	import fgame.scene.SceneManager;
	import fgame.unit.Actor3D;
	
	import flare.basic.Scene3D;
	import flare.collisions.CollisionInfo;
	import flare.collisions.RayCollision;
	import flare.collisions.SphereCollision;
	import flare.core.Pivot3D;
	import flare.system.Input3D;
	import flare.utils.Pivot3DUtils;
	
	import flash.events.Event;
	import flash.geom.Vector3D;
	import flash.net.drm.VoucherAccessInfo;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	
	import net.handler.Handler;
	
	import ricky.utils.TimeServer;


	public class Controller
	{
		public function Controller()
		{
			_stateDic=new Dictionary();
		}
		
		////////////////////////////////////////////////////////////////////
		//**************** public **********************
		////////////////////////////////////////////////////////////////////

		public function get pingEnable():Boolean
		{
			return _pingEnable;
		}

		public function set pingEnable(value:Boolean):void
		{
			_pingEnable = value;
		}

		public function get controlEnable():Boolean
		{
			return _controlEnable;
		}

		public function set controlEnable(value:Boolean):void
		{
			_controlEnable = value;
		}

		public function get cameraFllowEnable():Boolean
		{
			return _cameraFllowEnable;
		}

		public function set cameraFllowEnable(value:Boolean):void
		{
			_cameraFllowEnable = value;
		}

		public function get graphic():Pivot3D
		{
			return _graphic;
		}

		public function updateEvent(e:Event=null):void
		{
			if(this._pingEnable)
				this.ping();
			
			if(!_controlEnable)
				return;
			
			if(Input3D.keyHit(Input3D.A))
				this.chooseState(Input3D.A);
			else if(Input3D.keyHit(Input3D.UP) || Input3D.keyHit(Input3D.LEFT) ||Input3D.keyHit(Input3D.RIGHT)||Input3D.keyHit(Input3D.DOWN))
			{
				this.chooseState(Input3D.UP);
			}else if(Input3D.keyHit( Input3D.SPACE) )
				this.chooseState(Input3D.SPACE);
//			else if(!(Input3D.keyDown(Input3D.UP) || Input3D.keyDown(Input3D.LEFT) ||Input3D.keyDown(Input3D.RIGHT)||Input3D.keyDown(Input3D.DOWN)))
//			{
//				this.chooseState(-1);
//			}
			var t:Number=TimeServer.now();
			if(_currState)
				_currState.action(t);
			
			if(_cameraFllowEnable)
			{
				var scene:Scene3D=GameState.inst.scene;
				Pivot3DUtils.setPositionWithReference( scene.camera, 0, 400, 600, _graphic, 0.2 );
				Pivot3DUtils.lookAtWithReference( scene.camera, 0, 5, 0, _graphic );
			}else
			{
				var sm:SceneManager=GameState.inst.sceneManager;
				if(sm.cameraRoot)
					Pivot3DUtils.setPositionWithReference(sm.cameraRoot, 0, 0, 0, _graphic, 0.2 );
			}
			
		}
		
		
		
		public function registState():void
		{
			_stateDic[Input3D.A]=new AttackState(this);
			_stateDic[Input3D.A].completeFun=onComplete;
			_stateDic[Input3D.UP]=new MoveState(this);// ControllState(this);
			_stateDic[Input3D.UP].completeFun=onComplete;
			_stateDic[Input3D.SPACE]=new JumpState(this);
			_stateDic[Input3D.LEFT]=_stateDic[Input3D.UP];
			_stateDic[Input3D.RIGHT]=_stateDic[Input3D.UP];
			_stateDic[Input3D.DOWN]=_stateDic[Input3D.UP];
			_stateDic[200]=new MapClickState(this);
			_stateDic[-1]=new State(this);
			_stateDic[-1].completeFun=onComplete;
		}
		
		
		public function chooseState(state:int):void
		{
			var sta:State=_stateDic[state];
			if(sta)
				this.switchSate(sta);
			else
				this.switchSate(_stateDic[-1]);
		}
		
		/**
		 * 点击地图
		 */
		public function mapClick(target:Vector3D):void
		{
			_stateDic[200].info=target;
			switchSate(_stateDic[200]);
		}
		
		////////////////////////////////////////////////////////////////////
		//**************** protected **********************
		////////////////////////////////////////////////////////////////////
		
		/**
		 * ping网络
		 */
		protected function ping():void
		{
			_now=getTimer();
			_dt=_now-_lastTime;
			
			if(_dt>3000) //每两秒ping一次
			{
				_lastTime=_now;
				if(Handler.isPingSend)
					Handler.isPingSend=false;
				Handler.sendPing();
			}
		}
		
		protected function onComplete(state:State):void
		{
			state.end();
			_currState=_stateDic[-1];
			_currState.begin();
		}
		
		/**
		 * 选择状态
		 */
		protected function switchSate(state:State):void
		{
//			if(state==_currState && state is MoveAct)
//				return;
			
			if(_currState)
				_currState.end();
			
			_currState=state;
			_currState.begin();
		}
		////////////////////////////////////////////////////////////////////
		//**************** 属性 **********************
		////////////////////////////////////////////////////////////////////
		
		public function get rayCollisions():RayCollision
		{
			return _rayCollisions;
		}
		
		/**
		 * 地图加载完成后自动设置
		 */
		public function set rayCollisions(value:RayCollision):void
		{
			_rayCollisions = value;
		}
		
		public function get target():Actor3D
		{
			return _target;
		}
		
		public function set target(value:Actor3D):void
		{
			_target = value;
			if(_target)
			{
				_graphic=_target.graphic as Pivot3D;
				
				var sm:SceneManager=GameState.inst.sceneManager;
				
//				if(sm.cameraRoot)
//					_graphic.addChild(sm.cameraRoot);
				
				if(sm.camera)
					GameState.inst.scene.camera=sm.camera;
			}
			else
				_graphic=null;
			
			
		}
		
		
		////////////////////////////////////////////////////////////////////
		//**************** private **********************
		////////////////////////////////////////////////////////////////////
		private var _target:Actor3D;
		private var _rayCollisions:RayCollision;
		private var _graphic:Pivot3D;
		private var _stateDic:Dictionary;
		/** 当前状态 */
		private var _currState:State;
		private var _cameraFllowEnable:Boolean=false;
		private var _controlEnable:Boolean=false;
		//
		//
		private var _lastTime:Number=0;
		private var _dt:Number=0;
		private var _now:Number=0;
		private var _pingEnable:Boolean=false;
		////////////////////////////////////////////////////////////////////
		//**************** static**********************
		////////////////////////////////////////////////////////////////////
		
		private static var _instance:Controller;
		
		public static function get instance():Controller
		{
			if(_instance==null)
			{
				_instance=new Controller();
				_instance.registState();
//				_instance.chooseState(Input3D.UP);
			}
			return _instance;
		}
	}
}